home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1986-01-23 | 8.0 KB | 283 lines |
- IMPLEMENTATION MODULE Srecord;
- (* Creates Motorola S-records of program: *)
- (* S0 = header record, *)
- (* S2 = code/data records (24 bit address), *)
- (* S8 = termination record (24 bit address). *)
-
- FROM FileSystem IMPORT
- File, WriteChar;
-
- FROM Strings IMPORT
- Length;
-
- FROM LongNumbers IMPORT
- LONG, LongAdd, LongSub, LongInc, LongDec, LongClear,
- LongCompare, CardToLong, LongPut;
-
- IMPORT ASCII;
-
-
- CONST
- CountMAX = 16;
- SrecMAX = CountMAX * 2;
- XrecMAX = SrecMAX;
-
-
- VAR
- StartAddr : LONG; (* address that record starts on *)
- TempAddr : LONG; (* running address of where we are now *)
- CheckSum : LONG;
- Count : CARDINAL; (* count of HEX-pairs in S-record *)
- Sdata : ARRAY [1..SrecMAX] OF INTEGER; (* S-record data, HEX digits *)
- Sindex : CARDINAL; (* index for Sdata array *)
- Xdata : ARRAY [1..XrecMAX] OF INTEGER; (* Overflow for Sdata *)
- Xindex : CARDINAL; (* index for Xdata array *)
- Boundary : BOOLEAN; (* marks Address MOD 16 boundary of S-record *)
- LZero : LONG; (* used as a constant = 0 *)
-
-
-
- PROCEDURE Complement; (* CheckSum *)
- BEGIN
- LongSub (LZero, CheckSum, CheckSum); (* 2's Complement *)
- LongDec (CheckSum, 1); (* Make it 1's Complement *)
- END Complement;
-
-
-
- PROCEDURE AppendSdata (Data : LONG; n : CARDINAL) : BOOLEAN;
- (* Transfers data to Sdata, and updates Count & CheckSum. *)
- (* If no room: Data goes to Xdata & FALSE returned. *)
-
- VAR
- T : LONG; (* temporary -- used only as a 2 digit HEX number *)
-
- BEGIN
- T := LZero;
-
- WHILE (n # 0) AND (Count # CountMAX) AND (NOT Boundary) DO
- Sdata[Sindex] := Data[n];
- Sdata[Sindex - 1] := Data[n - 1];
-
- T[2] := Data[n]; T[1] := Data[n - 1];
- LongAdd (T, CheckSum, CheckSum);
-
- DEC (n, 2);
- DEC (Sindex, 2);
- INC (Count);
-
- LongInc (TempAddr, 1);
- IF TempAddr[1] = 0 THEN (* i.e., TempAddr MOD 16 = 0 *)
- Boundary := TRUE;
- END;
- END;
-
- IF (Count = CountMAX) OR (Boundary) THEN
- WHILE n > 0 DO (* Add Data to Xdata (in reverse) *)
- INC (Xindex);
- Xdata[Xindex] := Data[n];
- DEC (n);
- END;
-
- RETURN FALSE; (* Sdata is full *)
- ELSE
- RETURN TRUE;
- END;
- END AppendSdata;
-
-
-
- PROCEDURE DumpSdata (VAR f : File);
- (* Writes an S2 record to the file *)
-
- VAR
- T : LONG; (* temporary -- used to output Count & CheckSum *)
- i, j : CARDINAL;
-
- BEGIN
- IF Count = 0 THEN
- RETURN; (* nothing to dump *)
- END;
-
- WriteChar (f, 'S');
- WriteChar (f, '2');
-
- CardToLong (Count + 4, T); (* extra for Address & Checksum *)
- LongPut (f, T, 2);
- LongAdd (T, CheckSum, CheckSum); (* Add Count to CheckSum *)
-
- LongPut (f, StartAddr, 6);
- (* Add Address to CheckSum *)
- T := LZero;
- T[1] := StartAddr[1]; T[2] := StartAddr[2];
- LongAdd (T, CheckSum, CheckSum);
- T[1] := StartAddr[3]; T[2] := StartAddr[4];
- LongAdd (T, CheckSum, CheckSum);
- T[1] := StartAddr[5]; T[2] := StartAddr[6];
- LongAdd (T, CheckSum, CheckSum);
-
- IF Count < CountMAX THEN (* adjust short record -- shuffle down *)
- j := 1;
- FOR i := Sindex + 1 TO SrecMAX DO
- Sdata[j] := Sdata[i];
- INC (j);
- END;
- END;
- LongPut (f, Sdata, Count * 2); (* S-record Code/Data *)
-
- Complement; (* CheckSum *)
- LongPut (f, CheckSum, 2);
-
- WriteChar (f, ASCII.cr);
- WriteChar (f, ASCII.lf);
-
- LongInc (StartAddr, Count);
- Sindex := SrecMAX;
- Count := 0;
- Boundary := FALSE;
- CheckSum := LZero;
- END DumpSdata;
-
-
-
- PROCEDURE GetXdata;
- (* Transfer Xdata into new Sdata line -- N.B.: Xdata stored in reverse *)
-
- VAR
- i : CARDINAL;
- T : LONG;
-
- BEGIN
- i := 1;
- T := LZero;
-
- (* No need for either of the tests (CountMAX or Boundary) *)
- (* used in AppendSdata. GetXdata is only ever called *)
- (* after DumpSdata and is therefore only putting (up to 20) *)
- (* HEX digits in an empty buffer (which could hold 32). *)
- WHILE i < Xindex DO
- Sdata[Sindex] := Xdata[i];
- Sdata[Sindex - 1] := Xdata[i + 1];
- T[2] := Sdata[Sindex]; T[1] := Sdata[Sindex - 1];
- LongAdd (T, CheckSum, CheckSum);
- INC (i, 2);
- DEC (Sindex, 2);
- INC (Count);
- LongInc (TempAddr, 1);
- END;
-
- Xindex := 0;
- END GetXdata;
-
-
-
- PROCEDURE StartSrec (VAR f : File; SourceFN : ARRAY OF CHAR);
- (* Writes S0 record (HEADER) and initializes *)
-
- VAR
- T : LONG; (* temporary *)
- i : CARDINAL;
-
- BEGIN
- WriteChar (f, 'S');
- WriteChar (f, '0');
-
- CheckSum := LZero;
- Count := Length (SourceFN) + 3; (* extra for Address & Checksum *)
- CardToLong (Count, T);
- LongPut (f, T, 2);
- LongAdd (T, CheckSum, CheckSum);
-
- LongPut (f, LZero, 4); (* Address is 4 digit, all zero, for S0 *)
-
- i := 0;
- WHILE SourceFN[i] # 0C DO
- CardToLong (ORD (SourceFN[i]), T);
- LongAdd (T, CheckSum, CheckSum);
- LongPut (f, T, 2);
- INC (i);
- END;
-
- Complement; (* CheckSum *)
- LongPut (f, CheckSum, 2);
-
- WriteChar (f, ASCII.cr);
- WriteChar (f, ASCII.lf);
-
- Sindex := SrecMAX;
- Xindex := 0;
- Count := 0;
- Boundary := FALSE;
- CheckSum := LZero;
- StartAddr := LZero;
- TempAddr := LZero;
- END StartSrec;
-
-
-
- PROCEDURE WriteSrecLine (VAR f : File;
- AddrCnt, ObjOp, ObjSrc, ObjDest : LONG;
- nA, nO, nS, nD : CARDINAL);
- (* Collects Object Code -- Writes an S2 record to file if line is full *)
-
- VAR
- dummy : BOOLEAN;
-
- BEGIN
- IF nA = 0 THEN
- RETURN; (* Nothing to add to S-record *)
- END;
-
- IF Xindex # 0 THEN
- GetXdata; (* transfers Xdata into Sdata *)
- END;
-
- IF LongCompare (AddrCnt, TempAddr) # 0 THEN
- DumpSdata (f);
- END;
-
- IF Count = 0 THEN
- StartAddr := AddrCnt;
- TempAddr := AddrCnt;
- END;
-
- dummy := AppendSdata (ObjOp, nO);
- dummy := AppendSdata (ObjSrc, nS);
- IF NOT AppendSdata (ObjDest, nD) THEN
- DumpSdata (f);
- END;
- END WriteSrecLine;
-
-
-
- PROCEDURE EndSrec (VAR f : File);
- (* Finishes off any left-over (Partial) S2 line, *)
- (* and then writes S8 record (TRAILER) *)
- BEGIN
- IF Xindex # 0 THEN
- GetXdata;
- END;
- DumpSdata (f);
-
- WriteChar (f, 'S'); (* Fixed format for S8 record *)
- WriteChar (f, '8');
- WriteChar (f, '0');
- WriteChar (f, '4');
- WriteChar (f, '0');
- WriteChar (f, '0');
- WriteChar (f, '0');
- WriteChar (f, '0');
- WriteChar (f, '0');
- WriteChar (f, '0');
- WriteChar (f, 'F');
- WriteChar (f, 'C');
- WriteChar (f, ASCII.cr);
- WriteChar (f, ASCII.lf);
- WriteChar (f, ASCII.cr);
- WriteChar (f, ASCII.lf);
- END EndSrec;
-
- BEGIN (* Initialization *)
- LongClear (LZero);
- END Srecord.